package org.sgx.jsutil.client;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.UListElement;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;

public class DOMUtil {

	public static interface EventHandler {
		void onEvent(Event event);
	}
	public static void addClickHandler(Element e, final EventHandler handler) {
		addClickHandler(e, handler, false); 
	}
	
	public static final String EVENT_CLICK="click"; 
	
	public static void addClickHandler(Element e, final EventHandler handler, final boolean preventDefault) {
		addEventHandler(e, EVENT_CLICK, handler, preventDefault); 
//		DOM.sinkEvents((com.google.gwt.user.client.Element) e, Event.ONCLICK);
//		DOM.setEventListener((com.google.gwt.user.client.Element) e, new EventListener() {
//			@Override
//			public void onBrowserEvent(Event event) {
//				final int thisEventTypeInt = Event.getTypeInt(event.getType());
//				if(thisEventTypeInt!=Event.ONCLICK)
//					return; 
//				if(preventDefault)
//					event.preventDefault(); 
//				handler.onEvent(event);
//			}
//		});
	}
	public static void addEventHandler(Element e, final String type, 
			final EventHandler handler, final boolean preventDefault) {
		addEventHandler(e, type, handler, preventDefault, false);
	}
	public static void addEventHandler(Element e, final String type, 
			final EventHandler handler, final boolean preventDefault, final boolean stopPropagation) {
		final int origEventTypeInt = Event.getTypeInt(type); 
//		System.out.println("addEventHandler: "+origEventTypeInt);
		DOM.sinkEvents((com.google.gwt.user.client.Element) e, origEventTypeInt);
		DOM.setEventListener((com.google.gwt.user.client.Element) e, new EventListener() {
			@Override
			public void onBrowserEvent(Event event) {
//				System.out.println("trigger type "+event.getType());
				final int thisEventTypeInt = Event.getTypeInt(event.getType());
				if(thisEventTypeInt!=origEventTypeInt)
					return; 
				if(preventDefault)
					event.preventDefault(); 
				if(stopPropagation)
					event.stopPropagation(); 
				handler.onEvent(event);
			}
		});
	}
	
//	private int eventToInt(String event) {
//		if(event==null)
//			return -1; 
//		if(event.equals(EVENT_CLICK))
//			return Event.ONCLICK; 
//		else
//			return -1; 
//	}

	
	public static void clear(Element e) {
			while(e.getLastChild()!=null)
				e.removeChild(e.getLastChild());
	//		NodeList<Node> childs = e.getChildNodes();
	//		for (int i = 0; i < childs.getLength(); i++) {
	//			e.removeChild(childs.getItem(i));
	//		}
		}

	private static int counter=0; 
	public static String setId(Element element) {
		counter++; 
		String id = "domutil_id_"+counter; 
		element.setId(id);
		return id; 
	}

	public native final static NodeList querySelectorAll(Element e, String s)/*-{
		if(!e.querySelectorAll)
			return null; 
		else
			return e.querySelectorAll(s);
	}-*/;


/**
 * @see http://stackoverflow.com/questions/9334645/create-node-from-markup-strin
 * @param element
 * @param html
 * @return the inserted nodes
 */
public static native JsArray<Element> appendStringAsNodes(Element element, String html)/*-{
	var frag = document.createDocumentFragment(),
        tmp = document.createElement('body'), child, ret = []; 
    tmp.innerHTML = html;
    // Append elements in a loop to a DocumentFragment, so that the browser does
    // not re-render the document for each node
    while (child = tmp.firstChild) {
        frag.appendChild(child);
        ret.push(child);
    }
    element.appendChild(frag); // Now, append all elements at once
    frag = tmp = null;
    return ret;
}-*/;
/**
 * applies the template and append the result string as html nodes inside to given element. 
 * @param element
 * @param template
 * @param data
 * @param defaultVal
 * @return the inserted nodes
 */
public static JsArray<Element> appendTemplateAsNode(Element element, String template, JavaScriptObject data, String defaultVal) {
	String rendered = JsUtil.template(template, data, defaultVal);
	return appendStringAsNodes(element, rendered); 
}
/**
 * applies the template and append the result string as html nodes inside to given element. 
 * @param element
 * @param template
 * @param data
 * @return the inserted nodes
 */
public static JsArray<Element> appendTemplateAsNode(Element element, String template, String...data) {
	String rendered = JsUtil.template(template, data);
	return appendStringAsNodes(element, rendered); 
}
public static void hide(Element el) {
	el.getStyle().setProperty("display", "none"); 
}
public static void show(Element el) {
	el.getStyle().setProperty("display", "block"); 
}

}
